#pragma once
#ifndef RTCPMANAGER_H
#define RTCPMANAGER_H

#include <QByteArray>
#include <QtEndian>
namespace RTCP
{
    enum PacketType
    {
        SR = 200,   // Sender Report
        RR = 201,   // Receiver Report
        SDES = 202, // Source Description
        BYE = 203,  // Goodbye
        APP = 204,  // Application-Defined
        PSFB = 206, // Payload-Specific Feedback
    };
    enum FeedbackType
    {
        PLI = 1, // Picture Loss Indication
        FIR = 4, // Full Intra Request
    };
    struct Header
    {
        /* byte 0 */
        uint8_t version : 2;
        uint8_t padding : 1;
        uint8_t ic : 5; // 某些包类型中包含了一个list的条目，可能作为固定的、用于特定类 型的信息的补充

        /* byte 1 */
        uint8_t packetType; // 200=SR, 201=RR, 202=SDES, 203=BYE, 204=APP

        /* bytes 2, 3 */
        uint16_t length; // 包长度（以32位字为单位）

        inline uint16_t getLength() { return qFromBigEndian(length) * 4; }
    };

    union HeaderData
    {
        Header header;
        uint8_t data[sizeof(Header)];
    };

    // SR 200
    struct SenderReport
    {
        uint32_t ssrc;             // Source identifier
        uint32_t ntp_timestamp_ms; // 绝对 时间戳
        uint32_t ntp_timestamp_ls; // 相对 时间戳
        uint32_t rtp_timestamp;    // RTP timestamp
        uint32_t packet_count;     // 发送的数据包数
        uint32_t octet_count;      // 发送的字节数
    };

    struct ReceptionReport
    {
        uint32_t ssrc;            // Source identifier
        uint32_t fraction_lost;   // Fraction lost since last SR (or RR)
        uint32_t cumulative_lost; // Cumulative number of packets lost

        uint32_t extended_seq_num; // Extended highest sequence number received
    };

    // RFC 4585: Feedback format.
    //
    // Common packet format:
    //
    //   0                   1                   2                   3
    //   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    //  |V=2|P|   FMT   |       PT      |          length               |
    //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    //  |                  SSRC of packet sender                        |
    //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    //  |                  SSRC of media source                         |
    //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    //  :            Feedback Control Information (FCI)                 :
    //  :                                                               :
    //
    // Picture loss indication (PLI) (RFC 4585).
    // FCI: no feedback control information.

    // PLI 206 发生关键帧丢失时, 请求发送关键帧
    struct PictureLossIndication
    { // FMT = 1, PT = 206
        Header header;

        uint32_t ssrc; // SSRC of packet sender

        uint32_t source_ssrc; // SSRC of media source
    };

    // FIR 206 未发生关键帧丢失时, 请求发送关键帧
    struct FullIntraRequest
    {
        HeaderData hd; // FMT = ic = 4; PT = 206; length = 4 0x84 ce 00 04

        uint32_t ssrc;        // SSRC of packet sender
        uint32_t source_ssrc; // SSRC of media source (unused)

        // FCI:
        uint32_t media_ssrc;       // SSRC of media source
        uint16_t request_seq_num;  // Request sequence number
        uint16_t num_of_fragments; // Number of fragments
    };

    inline void parsePacket(const QByteArray &packet)
    {
        const Header *header = reinterpret_cast<const Header *>(packet.constData());
        PacketType packetType = static_cast<PacketType>(header->packetType);
        switch (packetType)
        {
        case SR:
            break;
        case RR:
            break;
        case SDES:
            break;
        case BYE:
            break;
        case APP:
            break;
        case PSFB:
            break;
        default:
            break;
        }
    }
    inline QByteArray getFirPacket(uint32_t senderSsrc, uint32_t mediaSsrc, uint16_t requestSeqNum)
    {
        FullIntraRequest fir;
        fir.hd.data[0] = 0x84;
        fir.hd.header.packetType = PSFB;
        fir.hd.header.length = 4 << 8;
        fir.ssrc = qToBigEndian(senderSsrc);
        fir.source_ssrc = 0;
        fir.media_ssrc = qToBigEndian(mediaSsrc);
        fir.request_seq_num = 0;
        fir.num_of_fragments = 0;
        return QByteArray(reinterpret_cast<const char *>(&fir), sizeof(fir));
    }
}

#endif